package priv.bestbeat.cloud.api.gateway.configurations.security;

import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.util.matcher.PathPatternParserServerWebExchangeMatcher;

/**
 * webFlux 安全配置
 * @author 张渠钦
 * @date 2022/1/5 14:41
 */
@EnableWebFluxSecurity
public class SecurityConfiguration {

    @Bean
    public SecurityWebFilterChain springSecurityWebFilterChain(ServerHttpSecurity http) {
        return http
                .authorizeExchange(authorizeExchangeSpec -> {
                    authorizeExchangeSpec.anyExchange().authenticated();
                })
                .httpBasic().disable()
                .csrf().disable()
                .formLogin(formLoginSpec -> formLoginSpec
                        .requiresAuthenticationMatcher(new PathPatternParserServerWebExchangeMatcher("/login", HttpMethod.POST))
                        .authenticationFailureHandler(new UserAuthenticationFailureHandler())
                        .authenticationSuccessHandler(new UserAuthenticationSuccessHandler())
                        .disable() // 禁用默认表单功能，原因只支持 Content-type: x-www-form-urlencoded,重写 FormLoginSpec configure方法 converter
                ).exceptionHandling(exceptionHandlingSpec -> exceptionHandlingSpec
                        .authenticationEntryPoint(new UserAuthenticationEntryPoint())
                        .accessDeniedHandler(new UserAccessDeniedHandler())
                )
                .build();

    }

    @Bean
    public MapReactiveUserDetailsService userDetailsService() {
        UserDetails user = User.withDefaultPasswordEncoder()
                .username("user")
                .password("user")
                .roles("USER")
                .build();
        return new MapReactiveUserDetailsService(user);
    }

}
